/**
 @file sys_usw_ip_tunnel.h

 @date 2011-11-07

 @version v2.0

*/
#ifndef _SYS_USW_IP_TUNNEL_H
#define _SYS_USW_IP_TUNNEL_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_const.h"
#include "ctc_vector.h"
#include "ctc_hash.h"

#include "ctc_ipuc.h"
/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/
 enum sys_ip_tunnel_lookup_mode_e
{
    SYS_NAT_HASH_LOOKUP        =0x01,           /* NAT HASH is used to lookup NAT entry */
    SYS_NAT_TCAM_LOOKUP        =0x02           /* NAT HASH is used to lookup NAT entry */
};
typedef enum sys_ip_tunnel_lookup_mode_e sys_ip_tunnel_lookup_mode_t;

typedef struct
{
    union {
        ip_addr_t ipv4;
        ipv6_addr_t ipv6;
    }new_ipsa;
    uint16 new_l4_src_port;
    uint16 offset;
    uint32 sa_edit_ptr;
}sys_ip_tunnel_natsa_ad_t;

struct sys_ip_tunnel_natsa_info_s
{
    /*key*/
    ip_addr_t ipsa;
    uint16 vrf_id;
    uint16 l4_src_port;
    uint32  masklen:8;
    uint32  is_tcp_port:1;
    /*action*/
    uint32  in_tcam:1;
    uint32  new_ip_ver:2;
    uint32  key_offset:20;
    sys_ip_tunnel_natsa_ad_t ad;
};
typedef struct sys_ip_tunnel_natsa_info_s sys_ip_tunnel_natsa_info_t;

struct sys_ip_tunnel_natsa_v6_info_s
{
    /*key*/
    ipv6_addr_t ipsa;
    uint16 vrf_id;
    uint16 l4_src_port;
    uint32  masklen:8;
    uint32  is_tcp_port:1;
    /*action*/
    uint32  in_tcam:1;
    uint32  new_ip_ver:2;
    uint32  key_offset:16;
    uint32  rsv:4;
    sys_ip_tunnel_natsa_ad_t ad;
};
typedef struct sys_ip_tunnel_natsa_v6_info_s sys_ip_tunnel_natsa_v6_info_t;

struct sys_ip_tunnel_natsa_info_temp_s
{
    union {
        ip_addr_t ipv4;
        ipv6_addr_t ipv6;
    }ipsa;
    uint16 vrf_id;
    uint16 l4_src_port;
    uint32  masklen:8;
    uint32  is_tcp_port:1;
    uint32  ip_ver:2;
    uint32  new_ip_ver:2;
    /*action*/
    uint32  in_tcam:1;
    uint32  key_offset:16;
    uint32  rsv:2;
    sys_ip_tunnel_natsa_ad_t ad;
    void*   hash_node;
};
typedef struct sys_ip_tunnel_natsa_info_temp_s sys_ip_tunnel_natsa_info_temp_t;

struct sys_tunnel_ofb_cb_s
{
    uint32 ip_ver :1;
    uint32 rsv:31;
    void* p_nat_info;
};
typedef struct sys_tunnel_ofb_cb_s sys_tunnel_ofb_cb_t;

#define SYS_IP_TUNNEL_MAP_NATSA(p_natsa, p_natsa_db, key_only)    \
do {\
    sal_memcpy(&(p_natsa)->ipsa, &(p_natsa_db)->ipsa, (p_natsa)->ip_ver == CTC_IP_VER_6 ? sizeof(ipv6_addr_t) \
                                                                                        : sizeof(ip_addr_t));\
    (p_natsa)->vrf_id = (p_natsa_db)->vrf_id;\
    (p_natsa)->l4_src_port = (p_natsa_db)->l4_src_port;\
    (p_natsa)->is_tcp_port = (p_natsa_db)->is_tcp_port;\
    (p_natsa)->masklen = (p_natsa_db)->masklen;\
    if (0 == key_only) {\
        (p_natsa)->new_ip_ver = (p_natsa_db)->new_ip_ver;\
        (p_natsa)->in_tcam = (p_natsa_db)->in_tcam;\
        (p_natsa)->key_offset = (p_natsa_db)->key_offset;\
        sal_memcpy(&(p_natsa)->ad, &(p_natsa_db)->ad, sizeof(sys_ip_tunnel_natsa_ad_t));\
    }\
}while(0)

#define SYS_IP_TUNNEL_UNMAP_NATSA(p_natsa, p_natsa_db, key_only)   \
 do {\
    sal_memcpy(&(p_natsa_db)->ipsa, &(p_natsa)->ipsa, (p_natsa)->ip_ver == CTC_IP_VER_6 ? sizeof(ipv6_addr_t) \
                                                                                        : sizeof(ip_addr_t));\
    (p_natsa_db)->vrf_id = (p_natsa)->vrf_id;\
    (p_natsa_db)->l4_src_port = (p_natsa)->l4_src_port;\
    (p_natsa_db)->is_tcp_port = (p_natsa)->is_tcp_port;\
    (p_natsa_db)->masklen = (p_natsa)->masklen;\
    if (0 == key_only) {\
        (p_natsa_db)->new_ip_ver = (p_natsa)->new_ip_ver;\
        (p_natsa_db)->in_tcam = (p_natsa)->in_tcam;\
        (p_natsa_db)->key_offset = (p_natsa)->key_offset;\
        sal_memcpy(&(p_natsa_db)->ad, &(p_natsa)->ad, sizeof(sys_ip_tunnel_natsa_ad_t));\
    }\
 }while(0)

 struct sys_ip_tunnel_master_s
{
    sal_mutex_t* mutex;
    ctc_hash_t*  nat_hash[MAX_CTC_IP_VER];
    uint32 max_snat_tcam_num;
    uint32 napt_hash_count; /*napt store in host1 Daport hash*/
    uint32 snat_hash_count; /*snat store in host1 SaPort hash*/
    uint32 snat_tcam_count; /*snat store in tcam*/
    uint8 lookup_mode[MAX_CTC_IP_VER];
    uint8 ofb_type_nat_tcam;
};
typedef struct sys_ip_tunnel_master_s sys_ip_tunnel_master_t;

#define SYS_IPUC_NAT_KEY_MAP(p_ctc_nat, p_sys_nat)        \
    {                                                       \
        (p_sys_nat)->ip_ver = (p_ctc_nat)->ip_ver;        \
        (p_sys_nat)->vrf_id = (p_ctc_nat)->vrf_id;        \
        (p_sys_nat)->l4_src_port = (p_ctc_nat)->l4_src_port;      \
        (p_sys_nat)->masklen = (p_ctc_nat)->masklen;      \
        sal_memcpy(&(p_sys_nat)->ipsa, &(p_ctc_nat)->ipsa,\
                   (p_ctc_nat)->ip_ver == CTC_IP_VER_6 ? sizeof(ipv6_addr_t): sizeof(ip_addr_t));\
        if ((p_sys_nat)->l4_src_port > 0)   \
        {   \
            (p_sys_nat)->is_tcp_port = ((p_ctc_nat)->flag & CTC_IPUC_NAT_FLAG_USE_TCP_PORT) ? 1:0; \
        }   \
        if(DRV_IS_AT(lchip) && IS_MAX_MASKLEN((p_ctc_nat)->ip_ver, (p_ctc_nat)->masklen))\
        {\
            (p_sys_nat)->masklen = 0;\
        }\
    }

#define SYS_IPUC_NAT_DATA_MAP(p_ctc_nat, p_sys_nat)                            \
    {                                                                            \
        (p_sys_nat)->ad.new_l4_src_port = (p_ctc_nat)->new_l4_src_port;      \
        sal_memcpy(&(p_sys_nat)->ad.new_ipsa, &(p_ctc_nat)->new_ipsa, sizeof(ipv6_addr_t)); \
    }

/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/
extern int32
sys_usw_ip_tunnel_add_natsa(uint8 lchip, ctc_ipuc_nat_sa_param_t* p_ip_tunnel_natsa_param);

extern int32
sys_usw_ip_tunnel_remove_natsa(uint8 lchip, ctc_ipuc_nat_sa_param_t* p_ip_tunnel_natsa_param);

extern int32
sys_usw_ip_tunnel_add_tunnel(uint8 lchip, ctc_ipuc_tunnel_param_t* p_ip_tunnel_param);

extern int32
sys_usw_ip_tunnel_remove_tunnel(uint8 lchip, ctc_ipuc_tunnel_param_t* p_ip_tunnel_param);

extern int32
sys_usw_ip_tunnel_set_natsa_entry_hit(uint8 lchip, ctc_ipuc_nat_sa_param_t* p_ip_tunnel_natsa_param, uint8 hit);

extern int32
sys_usw_ip_tunnel_get_natsa_entry_hit(uint8 lchip, ctc_ipuc_nat_sa_param_t* p_ip_tunnel_natsa_param, uint8* hit);

extern int32
sys_usw_ip_tunnel_init(uint8 lchip, uint8 napt_port_disable);

extern int32
sys_usw_ip_tunnel_deinit(uint8 lchip);

extern int32
sys_usw_ip_tunnel_show_natsa(uint8 lchip, ctc_ipuc_nat_sa_param_t * p_nat_info);

#ifdef __cplusplus
}
#endif

#endif

